﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Runtime.Remoting.Contexts;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Xml.Linq;
using Xceed.Wpf.Toolkit.PropertyGrid;

namespace SuporeSliplampApp.Template
{
    [TemplatePart(Name ="SwitchText",Type =typeof(USwitchButton))]
    public class USwitchButton:CheckBox
    {
        internal static event EventHandler _switchCheckedTypeEvent;
        static USwitchButton()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(USwitchButton),new FrameworkPropertyMetadata(typeof(USwitchButton)));
        }
        public USwitchButton()
        {
            _switchCheckedTypeEvent += _switchCheckedTypeEvent;
        }
        #region 定义枚举
        /// <summary>
        /// 开关文本方向枚举
        /// </summary>
        public enum OrientationEnum
        {
            Left,
            Right,
            Middle
        }
        #endregion

        #region 重写OnChecked and OnUnchecked
        /// <summary>
        /// OnUncheck事件
        /// </summary>
        /// <param name="e"></param>
        protected override void OnUnchecked(RoutedEventArgs e)
        {
            base.OnUnchecked(e);

            var SwitchEllipse = this.Template.FindName("SwitchEllipse", this) as Ellipse;

            var SwitchText = this.Template.FindName("SwitchText", this) as TextBlock;
            //模板居为中时 Middle显示的文本距离
            if (SwitchText != null && SwitchContentTemplate == OrientationEnum.Middle)
            {
                double txtX = SwitchText.ActualWidth;
                double SwitchTextX = this.Width - txtX - (SwitchEllipse.Width * 2) - 15;
                BeginStoryboard(CreatDoubleAnimation(SwitchText, false, new RepeatBehavior(1), "(UIElement.RenderTransform).(TranslateTransform.X)", SwitchTextX, 0.5));
            }
            BeginStoryboard(CreatDoubleAnimation(SwitchEllipse, false, new RepeatBehavior(1), "(UIElement.RenderTransform).(TranslateTransform.X)", 0, 0.5));
        }

        /// <summary>
        /// 单选按钮切换事件（置另一个同SwitchType类型的名称为未选中）
        /// </summary>
        /// <param name="e"></param>
        protected override void OnChecked(RoutedEventArgs e)
        {
            base.OnChecked(e);

            var SwitchEllipse = this.Template.FindName("SwitchEllipse", this) as Ellipse;

            var SwitchText = this.Template.FindName("SwitchText",this) as TextBlock;

            RadioSwitchChecked();//如果是单选按钮

            if (SwitchText != null && SwitchContentTemplate == OrientationEnum.Middle)
            { 
                double txtX = SwitchText.ActualWidth;
                double SwitchTextX = this.Width - txtX - (SwitchEllipse.Width *2) - 15;
                BeginStoryboard(CreatDoubleAnimation(SwitchText, false, new RepeatBehavior(1), "(UIElement.RenderTransform).(TranslateTransform.X)", SwitchTextX, 0.5));
            }

            double SwitchEllipseX = this.Width - (this.Height / 2) - 6;

            BeginStoryboard(CreatDoubleAnimation(SwitchEllipse, false, new RepeatBehavior(1), "(UIElement.RenderTransform).(TranslateTransform.X)", SwitchEllipseX, 0.5));
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void SwitchCheckedTypeEvent(object sender,EventArgs e)
        {
            if (sender is USwitchButton switchButton && switchButton != this && SwitchType == switchButton.SwitchType
                && Window.GetWindow(switchButton) == Window.GetWindow(this))
            {
                IsChecked = false;
            }
        }

        #region 依赖属性


        public SolidColorBrush ActiveBackground
        {
            get { return (SolidColorBrush)GetValue(ActiveBackgroundProperty); }
            set { SetValue(ActiveBackgroundProperty, value); }
        }

        // Using a DependencyProperty as the backing store for ActiveBackground.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ActiveBackgroundProperty =
            DependencyProperty.Register("ActiveBackground", typeof(SolidColorBrush), typeof(USwitchButton), 
                new PropertyMetadata(new SolidColorBrush(Colors.Green)));

        public SolidColorBrush  InactiveBackground
        {
            get { return (SolidColorBrush )GetValue(InactiveBackgroundProperty); }
            set { SetValue(InactiveBackgroundProperty, value); }
        }

        // Using a DependencyProperty as the backing store for InactiveBackground.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty InactiveBackgroundProperty =
            DependencyProperty.Register("InactiveBackground", typeof(SolidColorBrush ), typeof(USwitchButton),
                new PropertyMetadata(new SolidColorBrush(Colors.Gray)));


        public SolidColorBrush ActiveForeground
        {
            get { return (SolidColorBrush)GetValue(ActiveForegroundProperty); }
            set { SetValue(ActiveForegroundProperty, value); }
        }

        // Using a DependencyProperty as the backing store for ActiveForeground.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ActiveForegroundProperty =
            DependencyProperty.Register("ActiveForeground", typeof(SolidColorBrush), typeof(USwitchButton),
                new PropertyMetadata(new SolidColorBrush(Color.FromRgb(67,67,68))));



        [Category("自定义"),Description("该属性用于调整文字的未选中字体颜色")]
        public SolidColorBrush  InactiveForeground
        {
            get { return (SolidColorBrush )GetValue(InactiveForegroundProperty); }
            set { SetValue(InactiveForegroundProperty, value); }
        }

        // Using a DependencyProperty as the backing store for InactiveForeground.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty InactiveForegroundProperty =
            DependencyProperty.Register("InactiveForeground", typeof(SolidColorBrush ), typeof(USwitchButton), 
                new PropertyMetadata(new SolidColorBrush(Color.FromRgb(172,172,172))));



        [Category("自定义"),Description("该属性用于调整内部文字的显示位置")]
        public OrientationEnum SwitchContentTemplate
        {
            get { return (OrientationEnum)GetValue(SwitchContentTemplateProperty); }
            set { SetValue(SwitchContentTemplateProperty, value); }
        }

        // Using a DependencyProperty as the backing store for SwitchContentTemplate.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty SwitchContentTemplateProperty =
            DependencyProperty.Register("SwitchContentTemplate", typeof(OrientationEnum), typeof(USwitchButton), 
                new PropertyMetadata(OrientationEnum.Left,OnSwitchTypeChanged));


        [Category("自定义"),Description("该属性用于不选时文本")]
        public string ContentFalse
        {
            get { return (string)GetValue(ContentFalseProperty); }
            set { SetValue(ContentFalseProperty, value); }
        }

        // Using a DependencyProperty as the backing store for ContentFalse.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ContentFalseProperty =
            DependencyProperty.Register("ContentFalse", typeof(string), typeof(USwitchButton));


        [Category("自定义"),Description("选中时文本")]
        public string ContentTrue
        {
            get { return (string)GetValue(ContentTrueProperty); }
            set { SetValue(ContentTrueProperty, value); }
        }

        // Using a DependencyProperty as the backing store for ContentTrue.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ContentTrueProperty =
            DependencyProperty.Register("ContentTrue", typeof(string), typeof(USwitchButton));


        [Category("自定义"),Description("开关按钮圆角角度")]
        public double SwitchBorderRadius
        {
            get { return (double)GetValue(SwitchBorderRadiusProperty); }
            set { SetValue(SwitchBorderRadiusProperty, value); }
        }

        // Using a DependencyProperty as the backing store for SwitchBorderRadius.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty SwitchBorderRadiusProperty =
            DependencyProperty.Register("SwitchBorderRadius", typeof(double), typeof(USwitchButton), new PropertyMetadata(0.0));


        [Category("自定义"),Description("定义一组开关，值相同则单向选")]
        public string SwitchType
        {
            get { return (string)GetValue(SwitchTypeProperty); }
            set { SetValue(SwitchTypeProperty, value); }
        }

        // Using a DependencyProperty as the backing store for SwitchType.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty SwitchTypeProperty =
            DependencyProperty.Register("SwitchType", typeof(string), typeof(USwitchButton), new PropertyMetadata(null,OnSwitchTypeChanged));

        private static void OnSwitchTypeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var uSwitch = (CheckBox)d;
            if (!string.IsNullOrEmpty(e.NewValue.ToString()))
            {
                _switchCheckedTypeEvent?.Invoke(uSwitch,new EventArgs());
            }
        }
        #endregion

        private static void OnSwitchTemplateChanged(DependencyObject obj,DependencyPropertyChangedEventArgs args)
        { 
            object oldValue = (object)args.OldValue;
            object newValue = (object)args.NewValue;
            var uSwitch = (USwitchButton)obj;
            if (oldValue != newValue) 
            {
                switch (newValue)
                {
                    case OrientationEnum.Right:
                        uSwitch.SwitchContentTemplate = OrientationEnum.Right; 
                        break;
                    case OrientationEnum.Middle:
                        break;
                    default:
                        break;
                }
            }
        }

        private void RadioSwitchChecked()
        {
            if (!string.IsNullOrEmpty(SwitchType))
            {
                _switchCheckedTypeEvent?.Invoke(this,new EventArgs());
            }
        }

        public void SwitchTemplateChanged()
        {
            OnApplyTemplate();
        }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            var SwitchText = GetTemplateChild("SwitchText") as TextBlock;
            if (SwitchText != null && SwitchContentTemplate == OrientationEnum.Right)
            {
                SwitchContentTranslateTransform(SwitchText);
            }
        }

        private void SwitchContentTranslateTransform(UIElement uIElement)
        {
            var tempX = this.Width / 2 +this.Height / 2+6;
            BeginStoryboard(CreatDoubleAnimation(uIElement,false,new RepeatBehavior(1),"(UIElement.RenderTransform).(TranslateTransform.X)",tempX,0));
        }
        #endregion

        #region 封装动画方法

        public void BeginStoryboard(DoubleAnimation doubleAnimation)
        {
            var storyboard = new Storyboard();
            storyboard.Children.Add(doubleAnimation);
            storyboard.Begin();
        }

        private DoubleAnimation CreatDoubleAnimation(UIElement uIElement,bool autoReverse, RepeatBehavior repeatBehavior,
            string propertyPath, double To, double fromSeconds)
        { 
            DoubleAnimation doubleAnimation = new DoubleAnimation();
            doubleAnimation.To = To;
            doubleAnimation.Duration = TimeSpan.FromSeconds(fromSeconds);
            doubleAnimation.RepeatBehavior = repeatBehavior;
            doubleAnimation.AutoReverse = autoReverse;
            Storyboard.SetTarget(doubleAnimation, uIElement);
            Storyboard.SetTargetProperty(doubleAnimation,new PropertyPath(propertyPath));
            return doubleAnimation;
        }
#endregion
    }
}
